<template>
  <div class="page-plat-workflow_setting">
    <div class="left">
      <input type="text" class="aimind-hidden-input" />
      <input type="password" class="aimind-hidden-input" />
      <Input
        v-model.trim="searchValue"
        placeholder="请输入工作流组件名称"
        :search="true"
        @on-search="handleTreeSearch"
      />
      <Tree class="workflow-tree" :data="compTreeData" :render="compTreeRender" ref="workflowTree"></Tree>
    </div>

    <div class="right">
      <div class="top" v-if="currentForm">
        <Input v-model="currentForm.name" placeholder="请输入节点" v-if="editNameShow" />
        <i v-if="editNameShow" class="iconfont icon-check" @click="changeCurrentName" title="确定修改"></i>
        <span v-else>
          {{currentForm.name}}
          <i
            class="iconfont icon-file-edit"
            @click="editNameShow = true"
            title="编辑名称"
          ></i>
        </span>
        <Button @click="cancelNode">取消</Button>
        <Button type="error" @click="delNode">删除</Button>
        <Button type="primary" @click="saveNode">保存</Button>
      </div>

      <Form
        ref="editForm"
        :model="currentForm"
        :label-width="100"
        class="workflow-edit-form"
        v-if="currentForm"
      >
        <FormItem label="所属分类：" prop="category" class="label-required">
          <Select v-model="currentForm.category.id">
            <Option
              v-for="(item,index) of categoryOptions"
              :key="index"
              :value="item.id"
            >{{item.title}}</Option>
          </Select>
        </FormItem>

        <FormItem label="描述：" prop="desc" class="label-required">
          <Input type="textarea" placeholder="请输入节点描述" v-model="currentForm.desc" />
        </FormItem>

        <FormItem label="运行环境：" prop="nodeType" class="label-required">
          <Select v-model="currentForm.nodeType.id">
            <Option
              v-for="(item,index) of nodeTypeOptions"
              :key="index"
              :value="item.id"
            >{{item.name}}</Option>
          </Select>
          <!-- <i class="iconfont icon-add"></i> -->
        </FormItem>

        <FormItem label="执行程序：" prop="bin" class="label-required">
          <Input placeholder="请输入执行程序" v-model="currentForm.bin" />
        </FormItem>

        <FormItem label="运行参数：" prop="args" class="label-required">
          <div v-if="currentForm.args.length">
            <ul class="arg-header">
              <li>参数名称</li>
              <li>英文名称</li>
              <li>参数类型</li>
              <li>默认值</li>
            </ul>

            <div class="arg-form" v-for="(item,index) of currentForm.args" :key="index">
              <FormItem>
                <Input v-model.trim="item.desc" placeholder="请输入参数名" clearable :maxlength="20" />
              </FormItem>
              <FormItem>
                <Input v-model.trim="item.name" placeholder="请输入英文名" clearable :maxlength="100" />
              </FormItem>
              <FormItem>
                <Select v-model="item.formEditType" @on-change="changeFormType(item)">
                  <Option
                    v-for="item in formEditTypeList"
                    :value="item.id"
                    :key="item.id"
                  >{{ item.value }}</Option>
                </Select>
              </FormItem>
              <FormItem style="width: 280px">
                <Input
                  v-model.trim="item.defaultValue"
                  placeholder="请输入参数默认值"
                  v-if="item.formEditType === 'string' || item.formEditType === 'file' || item.formEditType === 'select'  || item.formEditType === 'fields' || !item.formEditType"
                />
                <InputNumber
                  v-if="item.formEditType === 'double'"
                  :step="0.01"
                  placeholder="请输入参数默认值"
                  style="width: 100%"
                />
                <InputNumber
                  v-model.trim="item.defaultValue"
                  placeholder="请输入参数默认值"
                  v-if="item.formEditType === 'int'"
                  :precision="0"
                  style="width: 100%"
                />
                <RadioGroup
                  v-model="item.defaultValue"
                  v-if="item.formEditType === 'bool'"
                  style="text-align:center"
                >
                  <Radio label="true"></Radio>
                  <Radio label="false"></Radio>
                </RadioGroup>

                <Select
                  v-model="item.defaultValue"
                  v-if="item.formEditType === 'dataSelector' || item.formEditType === 'conceptSelector'"
                >
                  <Option
                    v-for="item in typeList"
                    :value="item.value"
                    :key="item.value"
                  >{{ item.label }}</Option>
                </Select>
              </FormItem>
              <i class="iconfont icon-trash" @click="del(index,'args')" title="删除参数"></i>
            </div>

            <Button size="small" type="primary" @click="argAdd">继续添加</Button>
          </div>
          <Button v-else size="small" type="primary" @click="argAdd">设置</Button>
        </FormItem>

        <FormItem label prop="dataFlow" class="checkbox-item">
          <Checkbox v-model="currentForm.dataFlow">数据流节点</Checkbox>
        </FormItem>

        <FormItem
          v-if="currentForm.dataFlow"
          prop="inputPorts"
          label="数据输入桩："
          class="label-required"
        >
          <div class="dataflow" v-if="currentForm.inputPorts.length">
            <ul class="dataflow-header">
              <li>英文名称</li>
              <li>描述</li>
              <li>类型</li>
            </ul>

            <div class="dataflow-form" v-for="(item,index) of currentForm.inputPorts" :key="index">
              <span class="order">{{index+1}}号输入桩：</span>
              <FormItem>
                <Input v-model.trim="item.argName" placeholder="请输入英文名称" clearable :maxlength="20" />
              </FormItem>
              <FormItem>
                <Input
                  v-model.trim="item.description"
                  placeholder="请输入描述"
                  clearable
                  :maxlength="20"
                />
              </FormItem>
              <FormItem>
                <Select v-model.trim="item.type">
                  <Option :value="0">数据表</Option>
                  <Option :value="1">模型输出</Option>
                  <Option :value="2">任务节点</Option>
                </Select>
              </FormItem>

              <i
                class="iconfont icon-up-arrow"
                @click="inputOutPortsUpDown(index,'up','inputPorts')"
                title="上移"
                v-show="index!==0"
              ></i>
              <i
                class="iconfont icon-down-arrow"
                @click="inputOutPortsUpDown(index,'down','inputPorts')"
                title="下移"
                v-show="index !== currentForm.inputPorts.length-1"
              ></i>

              <i class="iconfont icon-trash" @click="del(index,'inputPorts')" title="删除参数"></i>
            </div>

            <Button
              size="small"
              type="primary"
              @click="dataflowAdd('inputPorts')"
              style="position: relative;left: 20px;"
              v-show="currentForm.inputPorts.length < 4"
            >继续添加</Button>
          </div>
          <Button v-else size="small" type="primary" @click="dataflowAdd('inputPorts')">设置</Button>
        </FormItem>

        <FormItem
          v-if="currentForm.dataFlow"
          prop="outputPorts"
          label="数据输出桩："
          class="label-required"
        >
          <div class="dataflow" v-if="currentForm.outputPorts.length">
            <ul class="dataflow-header">
              <li>英文名称</li>
              <li>描述</li>
              <li>类型</li>
            </ul>

            <div class="dataflow-form" v-for="(item,index) of currentForm.outputPorts" :key="index">
              <span class="order">{{index+1}}号输出桩：</span>
              <FormItem>
                <Input v-model.trim="item.argName" placeholder="请输入英文名称" clearable :maxlength="20" />
              </FormItem>
              <FormItem>
                <Input
                  v-model.trim="item.description"
                  placeholder="请输入描述"
                  clearable
                  :maxlength="20"
                />
              </FormItem>
              <FormItem>
                <Select v-model.trim="item.type">
                  <Option :value="0">数据表</Option>
                  <Option :value="1">模型输出</Option>
                  <Option :value="2">任务节点</Option>
                </Select>
              </FormItem>

              <i
                class="iconfont icon-up-arrow"
                @click="inputOutPortsUpDown(index,'up','outputPorts')"
                title="上移"
                v-show="index!==0"
              ></i>
              <i
                class="iconfont icon-down-arrow"
                @click="inputOutPortsUpDown(index,'down','outputPorts')"
                title="下移"
                v-show="index !== currentForm.outputPorts.length-1"
              ></i>

              <i class="iconfont icon-trash" @click="del(index,'outputPorts')" title="删除参数"></i>
            </div>

            <Button
              size="small"
              type="primary"
              @click="dataflowAdd('outputPorts')"
              style="position: relative;left: 20px;"
              v-show="currentForm.outputPorts.length < 4"
            >继续添加</Button>
          </div>
          <Button v-else size="small" type="primary" @click="dataflowAdd('outputPorts')">设置</Button>
        </FormItem>

        <FormItem
          v-if="!currentForm.dataFlow"
          label
          prop="compatibleToDataFlow"
          class="checkbox-item"
        >
          <Checkbox v-model="currentForm.compatibleToDataFlow">兼容数据流</Checkbox>
        </FormItem>

        <!-- <FormItem label prop="isCustom" class="checkbox-item">
          <Checkbox v-model="currentForm.isCustom">自定义节点</Checkbox>
        </FormItem>-->

        <FormItem label="运行入口：" prop="commands" class="label-required">
          <template v-if="currentForm.commands.length">
            <div
              v-for="(item,index) of currentForm.commands"
              :key="index"
              style="margin-bottom: 10px;"
            >
              <Input type="textarea" placeholder="请输入执行程序" v-model="currentForm.commands[index]" />
              <i class="iconfont icon-trash" @click="del(index,'commands')" title="删除运行入口"></i>
            </div>
          </template>

          <Button
            size="small"
            type="primary"
            @click="commandsAdd"
            v-if="currentForm.commands.length === 0"
          >设置</Button>

          <Button size="small" type="primary" @click="commandsAdd" v-else>继续添加</Button>
        </FormItem>
      </Form>
    </div>

    <!-- 新增节点/分类 -->
    <Modal
      footer-hide
      title="创建工作流任务分类或节点"
      v-model="addVisible"
      width="500px"
      class="platform-workflownode-add"
    >
      <div class="add-item">
        <label for>添加类型：</label>
        <Select v-model="addType">
          <Option value="file">添加分类</Option>
          <Option value="node">添加节点</Option>
        </Select>
      </div>

      <div class="add-item" v-show="addType === 'node'">
        <label for>节点名称：</label>
        <Input placeholder="请输入节点名称" v-model.trim="addNodeName" />
      </div>

      <div class="add-item" v-show="addType === 'file'">
        <label for>分类名称：</label>
        <Input placeholder="请输入分类名称" v-model.trim="addFileName" />
      </div>

      <div class="add-name-footer">
        <Button @click="addCancelHandler" style="marigin-right: 10px;">取消</Button>
        <Button type="primary" @click="addOKHandler">{{addType === 'node' ? '添加节点' : '确定'}}</Button>
      </div>
    </Modal>

    <!-- 重命名工作流任务 -->
    <Modal
      footer-hide
      title="重命名工作流任务分类"
      v-model="editVisible"
      width="500px"
      class="platform-workflownode-add"
    >
      <div class="add-item">
        <label for>分类名称：</label>
        <Input placeholder="请输入工作流分类名称" v-model.trim="editFileName" />
      </div>

      <div class="add-name-footer">
        <Button @click="editCancelHandler" style="marigin-right: 10px;">取消</Button>
        <Button type="primary" @click="editOKHandler">确定</Button>
      </div>
    </Modal>
  </div>
</template>

<script>
import * as workflowApi from 'http/api/platform';
import { deepClone } from 'assets/scripts/common';
export default {
  data () {
    return {
      operateNode: null, // 记录当前操作的节点
      firstParentObj: {}, // 父级的名称和id
      parentIds: [], // 所有的父级ids
      parentIdsQueue: [],

      // 新增
      addType: 'node',
      addNodeName: '',
      addFileName: '',
      addVisible: false, // 新增节点弹窗

      // 编辑
      editVisible: false,
      editFileName: '',

      typeList: [
        // dataSelector
        {
          label: '数据集数据',
          value: 'ds'
        },
        {
          label: '图谱数据',
          value: 'cept'
        }
      ],

      valueLabels: [],

      formEditTypeList: [
        {
          id: 'string',
          value: '文本'
        },
        {
          id: 'int',
          value: '整型'
        },
        {
          id: 'bool',
          value: '布尔值'
        },
        {
          id: 'dataSelector',
          value: 'dataSelector'
        },
        {
          id: 'conceptSelector',
          value: 'conceptSelector'
        },
        {
          id: 'fields',
          value: 'fields'
        },
        {
          id: 'file',
          value: 'file'
        },
        {
          id: 'double',
          value: 'double'
        },
        {
          id: 'select',
          value: 'select'
        }
      ],
      currentForm: null,
      editNameShow: false,
      categoryOptions: [], // 所有的分类集合
      nodeTypeOptions: [], // 运行环境的集合
      searchValue: '',
      compTreeData: []
    };
  },
  methods: {
    // 获取父节点的时候需要做的事
    initParentObj () {
      this.firstParentObj = {}; // 直系父级的名称和id
      this.parentIds = []; // 所有的父级ids
      this.parentIdsQueue = []; // 排队的
    },

    // 初始化节点
    initNode () {
      return {
        name: '',
        category: {},
        desc: '',
        nodeType: {},
        bin: '',
        args: [],
        dataFlow: false,
        compatibleToDataFlow: false,
        isCustom: false,
        inputPorts: [],
        outputPorts: [],
        commands: []
      };
    },

    // 取消操作
    addCancelHandler () {
      this.addType = 'node';
      this.addNodeName = '';
      this.addFileName = '';
      this.addVisible = false; // 新增节点弹窗
      this.operateNode = null;
    },

    // 新增
    addOKHandler () {
      // 添加节点
      let param = {
        name: '',
        parent: {}
      };

      if (this.addType === 'node') {
        if (!this.addNodeName) {
          this.$Message.error('请先输入节点名称');
          return;
        } else {
          let { id, title } = this.operateNode;
          // 当前编辑的节点
          this.currentForm = deepClone(this.initNode());
          this.currentForm.name = this.addNodeName;
          this.currentForm.category = {
            id: id,
            name: title
          };

          // // 自定义节点
          // if (id === '0' && title === '自定义节点') {
          //   this.currentForm.isCustom = true;
          // }

          // 数据流组件
          if (id === '9' && title === '数据流组件') {
            this.currentForm.dataFlow = true;
          }
          this.addCancelHandler();
        }
      }

      // 添加文件夹--新增分类
      if (this.addType === 'file') {
        if (!this.addFileName) {
          this.$Message.error('请先输入文件夹名称');
        } else {
          // 请求添加的参数
          param.name = this.addFileName;
          param.parent.name = this.operateNode.title;
          param.parent.id = this.operateNode.id;

          workflowApi.addCategory(param).then(res => {
            if (res.data) {
              // 重新请求树
              this.findParentNode(this.operateNode.id);
              this.getTrees(this.parentIds);
              this.addCancelHandler();
            }
          });
        }
      }
    },

    // 取消编辑
    editCancelHandler () {
      this.editVisible = false;
      this.editFileName = '';
      this.operateNode = null;
    },

    // 编辑
    editOKHandler () {
      let param = {
        id: this.operateNode.id,
        name: this.editFileName,
        parent: {}
      };

      // 获取父节点
      this.findParentNode(this.operateNode.id);
      param.parent = this.firstParentObj;

      workflowApi.editCategory(param).then(res => {
        if (res.data) {
          this.getTrees(this.parentIds);
          this.editCancelHandler();
        }
      });
    },

    // 找到所有的父节点
    findParentNode (id, data) {
      // 初始化
      if (!data) {
        this.initParentObj();
      }

      data = data || this.compTreeData;
      this.parentIdsQueue = this.parentIdsQueue.concat(data);

      while (this.parentIdsQueue.length) {
        let item = this.parentIdsQueue.shift();

        let { children } = item;
        if (item.id === id) {
          this.parentIds = [];
          // 第一层就找到了
          if (!item.parentArr) {
            this.firstParentObj = {
              id: item.id,
              name: item.title
            };
            this.parentIds = [item.id];
          } else {
            let len = item.parentArr.length;
            this.firstParentObj = item.parentArr[len - 1];
            item.parentArr.forEach(a => {
              this.parentIds.push(a.id);
            });

            this.parentIds.push(item.id);
          }

          // 结束遍历
          this.parentIdsQueue = [];
          break;
        } else if (children && children.length) {
          let len = children.length;
          for (let i = len - 1; i >= 0; i--) {
            // 记录它的父亲节点
            children[i].parentArr = [];

            // 找它的父亲节点
            if (item.parentArr) {
              children[i].parentArr = children[i].parentArr.concat(
                item.parentArr
              );
            }
            children[i].parentArr.push({
              id: item.id,
              name: item.title
            });
            this.parentIdsQueue.unshift(children[i]);
          }
        }
      }
    },

    /**
     * 检索并控制搜索时相应的节点以及其祖先节点的打开状态（深度遍历链）
     * @param v 点击的树值
     */
    handleTreeSearch (v) {
      this.searchValue = v;
      if (!v) {
        return;
      }
      // 切换 expand 状态
      const loop = (node, depthList) => {
        const { children } = node;
        depthList.push(node);
        if (v && children) {
          const len = children.length;
          for (let i = 0; i < len; i++) {
            if (children[i].title.indexOf(v) > -1) {
              depthList.forEach(item => (item.expand = true));
            }
            loop(children[i], [...depthList]);
          }
        }
      };

      const treeData = deepClone(this.compTreeData);
      loop(
        {
          children: treeData,
          name: ''
        },
        []
      );
      this.compTreeData = treeData;
    },

    // 树节点绘制 render 函数
    compTreeRender (h, { root, node, data }) {
      const { selected, title: name } = data;
      let searchIndex = -1;
      let beforeStr = '';
      let afterStr = '';

      // 搜索词拆分逻辑
      if (name) {
        searchIndex = name
          .toLowerCase()
          .indexOf(this.searchValue.toLowerCase());
        beforeStr = name.substr(0, searchIndex);
        afterStr = name.substr(searchIndex + this.searchValue.length);
      }

      // 根据搜索词定制关键字render
      let nameRender = name;
      if (this.searchValue && searchIndex > -1) {
        nameRender = h('span', [
          beforeStr,
          h(
            'span',
            {
              style: 'color: #f50'
            },
            this.searchValue
          ),
          afterStr
        ]);
      }
      return h(
        'div',
        {
          class: `workflow-tree-node${
            data.categoryId || data.isCustom ? ' border-node' : ''
          }`
        },
        [
          h('span', [
            h(
              'span',
              {
                class: `workflow-tree-node-main${selected ? ' selected2' : ''}`,
                attrs: {
                  title: data.desc ? data.desc : nameRender
                },
                on: {
                  click: e => {
                    this.showNode(e, data);
                  }
                }
              },
              [nameRender]
            ),
            h('i', {
              class: `node-icon iconfont icon-file-edit hide`,
              attrs: {
                title: '编辑任务分类'
              },
              style: {
                position: 'relative',
                left: '17px',
                color: '#999999'
              },
              on: {
                click: () => {
                  this.editFile(data);
                }
              }
            }),
            h('i', {
              class: `node-icon iconfont icon-aimind-add-nor hide`,
              attrs: {
                title: '新增任务分类'
              },
              style: {
                position: 'relative',
                left: '25px',
                color: '#999999'
              },
              on: {
                click: () => {
                  this.addFile(data);
                }
              }
            }),
            h('i', {
              class: `node-icon iconfont icon-aimind-delete-nor hide`,
              attrs: {
                title: '删除任务分类'
              },
              style: {
                position: 'relative',
                left: '35px',
                color: '#999999'
              },
              on: {
                click: () => {
                  this.delFile(data);
                }
              }
            })
          ])
        ]
      );
    },

    /**
     * 树的数据改造
     * @param data 原始树数据
     */
    changeComTreeData (data) {
      for (let i = 0; i < data.length; i++) {
        let item = data[i];

        // 存储分类信息
        if (item.title && item.id && !item.categoryId && !item.isCustom) {
          this.categoryOptions.push({
            title: item.title,
            id: item.id,
            name: item.name
          });
        }

        if (item.children.length > 0) {
          this.changeComTreeData(item.children);
        }

        if (item.taskNodeDTOs.length > 0) {
          item.taskNodeDTOs.forEach(unit => {
            item.children.push(unit);
          });
        }

        delete item.taskNodeDTOs;
      }
      return data;
    },

    // 获取树数据
    getTrees (expandIds) {
      workflowApi.getCategories().then(res => {
        let initTree = this.changeComTreeData(res.data);

        // 自定义节点去除
        let customIndex = initTree.findIndex(item => {
          return item.id === '0';
        });
        initTree.splice(customIndex, 1);

        if (expandIds) {
          const findExpandNode = data => {
            for (let i = 0, len = data.length; i < len; i++) {
              if (expandIds.includes(data[i].id)) {
                data[i].expand = true;
              }

              if (data[i].children && data[i].children.length) {
                findExpandNode(data[i].children);
              }
            }
          };

          findExpandNode(initTree);
        }
        this.compTreeData = initTree;
      });
    },

    // 编辑节点
    editFile (data) {
      this.operateNode = data;
      this.editFileName = data.title;
      this.editVisible = true;
    },

    // 新增节点
    addFile (data) {
      this.operateNode = data;
      this.addVisible = true;
    },

    // 删除节点
    delFile (data) {
      this.$Modal.confirm({
        title: '删除提示',
        content: '确认删除该分类吗？',
        onOk: () => {
          workflowApi
            .delCategory({
              id: data.id
            })
            .then(res => {
              if (res.data) {
                this.findParentNode(data.id);
                this.getTrees(this.parentIds);
                setTimeout(() => {
                  this.$Message.success('删除成功');
                }, 500);
              }
            });
        },
        onCancel: () => {}
      });
    },

    // 显示节点的图标
    showNode (e, data) {
      // 所有的隐藏
      let icons = document.querySelectorAll('.node-icon');
      let mainNodes = document.querySelectorAll('.workflow-tree-node-main');
      for (let i = 0, len = icons.length; i < len; i++) {
        icons[i].classList.add('hide');
      }

      for (let i = 0, len = mainNodes.length; i < len; i++) {
        mainNodes[i].classList.remove('selected2');
      }

      // 当前选中
      let $target = e.target;
      $target.classList.add('selected2');

      if (!data.categoryId && !data.isCustom) {
        let currentIcons = $target.parentElement.querySelectorAll('.node-icon');
        for (let i = 0, len = currentIcons.length; i < len; i++) {
          currentIcons[i].classList.remove('hide');
        }

        this.currentForm = null;
      } else {
        // 请求节点详情
        workflowApi
          .getNodeDetail({
            id: data.id
          })
          .then(res => {
            console.log(11111111111)
            if (res.data) {
              let { data } = res;
              if (!data.args) {
                data.args = [];
              }
              // if (!data.category && data.isCustom) {
              //   data.category = {
              //     id: "0",
              //     name: "自定义节点"
              //   };
              // }

              if (!data.nodeType) {
                data.nodeType = {};
              }
              this.currentForm = res.data;
            }
          });
      }
    },

    // 修改current
    changeCurrentName () {
      let name = this.currentForm.name;
      if (!name || !name.trim()) {
        this.$Message.error('节点名称不能为空');
        return;
      }
      this.editNameShow = false;
    },

    // 获取tashTypes
    getNodeTypes () {
      workflowApi.getImageTypes().then(res => {
        if (res.data) {
          this.nodeTypeOptions = res.data;
        }
      });
    },

    // 改变form类型
    changeFormType (item) {
      let { formEditType } = item;
      switch (formEditType) {
        case 'int':
          item.defaultValue = 0;
          break;

        case 'bool':
          item.defaultValue = true;
          break;

        default:
          item.defaultValue = '';
      }
    },

    // 删除参数
    del (index, param) {
      this.currentForm[param].splice(index, 1);
    },

    // 增加参数
    argAdd () {
      let obj = {
        defaultValue: '',
        formEditType: 'string',
        name: '',
        value: ''
      };

      this.currentForm.args.push(obj);
    },

    // 增加输入桩
    dataflowAdd (type) {
      let obj = {
        argName: '',
        description: '',
        displayType: 'default',
        index: '',
        type: ''
      };

      this.currentForm[type].push(obj);
    },

    // 输入上移动
    inputOutPortsUpDown (index, type, nodeType) {
      // eslint-disable-next-line
      let currentItem = deepClone(this.currentForm[nodeType][index]);

      // 先删除
      this.currentForm[nodeType].splice(index, 1);
      // 再插入
      this.currentForm[nodeType].splice(
        type === 'down' ? index + 1 : index - 1,
        0,
        currentItem
      );
    },

    // 命令新增
    commandsAdd () {
      this.currentForm.commands.push('');
    },

    // 取消编辑
    cancelNode () {
      this.currentForm = null;
    },

    // 删除
    delNode () {
      this.$Modal.confirm({
        title: '删除提示',
        content: '确认删除该节点吗？',
        onOk: () => {
          if (this.currentForm.id) {
            workflowApi
              .delNode({
                id: this.currentForm.id
              })
              .then(res => {
                this.findParentNode(this.currentForm.id);
                this.getTrees(this.parentIds);
                this.currentForm = null;

                setTimeout(() => {
                  this.$Message.success('删除成功');
                }, 1000);
              });
          } else {
            this.currentForm = null;
            this.$Message.success('删除成功');
          }
        },
        onCancel: () => {}
      });
    },

    // 保存当前节点信息
    saveNode () {
      let {
        args,
        inputPorts,
        outputPorts,
        dataFlow,
        commands,
        desc,
        bin,
        nodeType,
        category,
        id
      } = this.currentForm;

      // 主参数必填校验
      if (!desc) {
        this.$Message.error('请输入节点描述');
        return false;
      }

      if (!nodeType.id) {
        this.$Message.error('请选择运行环境');
        return false;
      }

      if (!bin) {
        this.$Message.error('请输入执行程序');
        return false;
      }

      if (!args.length) {
        this.$Message.error('请至少设置一个运行参数');
        return false;
      }

      // 子参数校验
      if (args.length) {
        // 校验
        let isChecked = true;
        let names = [];
        let descs = [];

        args.forEach(item => {
          if (!item.name || !item.desc || !item.formEditType) {
            isChecked = false;
          }

          names.push(item.name);
          descs.push(item.desc);
        });

        if (!isChecked) {
          this.$Message.error('运行参数存在未填写的数据');
          return;
        }

        // 重复名字提示
        if (new Set(descs).size < descs.length) {
          this.$Message.error('运行参数的中文名称不可有重复');
          return;
        }
        if (new Set(names).size < names.length) {
          this.$Message.error('运行参数的英文名称不可有重复');
          return;
        }

        let isEnglish = true;

        names.find(item => {
          if (!/^[a-zA-Z]*$/.test(item)) {
            isEnglish = false;
          }
        });
        if (!isEnglish) {
          this.$Message.error('运行参数中的英文名称必须是英文');
          return;
        }
      }

      if (dataFlow && !inputPorts.length) {
        this.$Message.error('请至少设置一个数据输入桩');
        return false;
      }
      // 入
      if (dataFlow && inputPorts.length) {
        let inputFlag = true;
        let names = [];

        // 子参数校验
        inputPorts.forEach((item, index) => {
          if (!item.argName || !item.description || item.type === '') {
            inputFlag = false;
            return true;
          }

          item.index = index;
          names.push(item.argName);
        });

        if (!inputFlag) {
          this.$Message.error('数据输入桩存在未填写选项');
          return false;
        }

        if (new Set(names).size < names.length) {
          this.$Message.error('数据输入桩的英文名称不可有重复');
          return;
        }

        let isEnglish = true;
        names.find(item => {
          if (!/^[a-zA-Z]*$/.test(item)) {
            isEnglish = false;
          }
        });
        if (!isEnglish) {
          this.$Message.error('数据输入桩中的英文名称必须是英文');
          return;
        }
      }

      if (dataFlow && !outputPorts.length) {
        this.$Message.error('请至少设置一个数据输出桩');
        return false;
      }
      // 出
      if (dataFlow && outputPorts.length) {
        let outputFlag = true;
        let names = [];

        // 子参数校验
        outputPorts.forEach((item, index) => {
          if (!item.argName || !item.description || item.type === '') {
            outputFlag = false;
            return true;
          }

          item.index = index;
          names.push(item.argName);
        });

        if (!outputFlag) {
          this.$Message.error('数据输出桩存在未填写选项');
          return false;
        }

        if (new Set(names).size < names.length) {
          this.$Message.error('数据输出桩的英文名称不可有重复');
          return;
        }

        let isEnglish = true;
        names.find(item => {
          if (!/^[a-zA-Z]*$/.test(item)) {
            isEnglish = false;
          }
        });
        if (!isEnglish) {
          this.$Message.error('数据输出桩中的英文名称必须是英文');
          return;
        }
      }

      if (!commands.length) {
        this.$Message.error('请至少设置一个运行入口');
        return false;
      }

      let commandsFlag = true;
      commands.find(item => {
        if (!item) {
          commandsFlag = false;
          return true;
        }
      });

      if (!commandsFlag) {
        this.$Message.error('运行入口存在未填写选项');
        return false;
      }

      // nodeType
      this.nodeTypeOptions.find(item => {
        if (item.id === nodeType.id) {
          this.currentForm.nodeType = item;
          return true;
        }
      });

      this.categoryOptions.find(item => {
        if (item.id === category.id) {
          this.currentForm.category = { id: item.id, name: item.title };
          return true;
        }
      });
      console.log(this.currentForm);

      workflowApi[id ? 'editNode' : 'addNode'](this.currentForm).then(res => {
        if (res.data) {
          this.currentForm = null;

          this.findParentNode(res.data.id);
          this.getTrees(this.parentIds);

          setTimeout(() => {
            this.$Message.success(id ? '编辑成功' : '新增成功');
          }, 1000);
        }
      });
    }
  },
  mounted () {
    this.getTrees();
    this.getNodeTypes();
  }
};
</script>

<style rel="stylesheet/less" lang="less" scoped>
@import "../../assets/theme/themeBlue.less";
.page-plat-workflow_setting {
  background: #fff;
  height: 100%;
  .left {
    float: left;
    padding: 20px;
    max-height: 100%;
    width: 280px;
    overflow-y: auto;
  }
  .right {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 280px;
    overflow-y: auto;
    width: calc(100% - 280px);
    border-left: #ddd 1px solid;
    .top {
      padding: 20px;
      margin-bottom: 10px;
      border-bottom: #d6d6d6 1px solid;
      button {
        float: right;
        margin-right: 10px;
      }
    }
    .icon-file-edit,
    .icon-check {
      margin-left: 4px;
      cursor: pointer;
      &:hover {
        color: @primary;
      }
    }
    .icon-check {
      font-size: 26px;
      position: absolute;
      top: 16px;
    }
    .arg-header,
    .dataflow-header {
      margin-bottom: 8px;
      li {
        display: inline-block;
        width: 110px;
        text-align: center;
        font-weight: bold;
      }
    }
    .arg-form {
      position: relative;
      margin-bottom: 10px;
      .icon-trash {
        cursor: pointer;
        font-size: 18px;
        &:hover {
          color: @primary;
        }
      }
    }
    .dataflow-form {
      position: relative;
      margin-bottom: 10px;
      left: -80px;
      .order {
        display: inline-block;
        width: 80px;
        text-align: right;
      }
      .icon-trash,
      .icon-up-arrow,
      .icon-down-arrow {
        position: relative;
        cursor: pointer;
        font-size: 18px;
        &:hover {
          color: @primary;
        }
      }
    }
  }
}
</style>

<style lang="less">
@import "../../assets/theme/themeBlue.less";
.page-plat-workflow_setting {
  .workflow-tree {
    padding-left: 10px;
    .ivu-tree-arrow {
      position: relative;
      float: left;
      top: 2px;
    }
    .hide {
      display: none;
    }
  }
  .workflow-tree-node {
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-left: 16px;
    cursor: pointer;
    &.border-node {
      border: 1px solid #007bff;
      border-radius: 4px;
      line-height: 28px;
      height: 28px;
      .workflow-tree-node-main {
        top: 6px;
      }
      .icon-add {
        font-size: 14px;
        position: relative;
        top: -4px;
        left: 6px;
      }
      &.add-node {
        width: 128px;
        margin-left: 34px;
      }
    }
  }
  .workflow-tree-node-main {
    user-select: none;
    display: inline-block;
    max-width: 200px;
    text-overflow: ellipsis;
    overflow: hidden;
    position: relative;
    top: 3px;
    left: 8px;
    &.selected2 {
      color: @primary;
    }

    .ivu-icon {
      font-size: 18px;
    }
  }
  .right {
    .ivu-select,
    .ivu-input-wrapper {
      width: 280px;
    }
    .checkbox-item {
      .ivu-form-item-content {
        margin-left: 15px !important;
      }
    }
    .label-required {
      label:before {
        content: "*";
        display: inline-block;
        margin-right: 4px;
        line-height: 1;
        font-family: SimSun;
        font-size: 12px;
        color: #ed4014;
      }
      .ivu-radio-group label:before {
        display: none;
      }
    }
  }

  .arg-form .ivu-form-item,
  .dataflow-form .ivu-form-item {
    width: 110px;
    display: inline-block;
    .ivu-input-wrapper,
    .ivu-select {
      width: 100%;
    }
  }
}
.platform-workflownode-add {
  .add-item {
    position: relative;
    padding-left: 80px;
    margin-bottom: 20px;
    label {
      display: inline-block;
      position: absolute;
      top: 6px;
      left: 0;
      width: 80px;
      text-align: right;
    }
    .ivu-select,
    .ivu-input-wrapper {
      width: 280px;
    }
  }
  .add-name-footer {
    margin-top: 10px;
    text-align: right;
  }
}
</style>
